﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Linq;

namespace JyEditor
{
    public class BuildAssetBundleEditor : Singleton<BuildAssetBundleEditor>
    {
        /// <summary>
        /// 清理未使用的AssetBundle名字
        /// </summary>
        public void ClearUnusedAssetbundleNames()
        {
            AssetDatabase.RemoveUnusedAssetBundleNames();
        }

        /// <summary>
        /// 清理所有的AssetBundle名字
        /// </summary>
        public void ClearAllAssetbundleNames()
        {
            var names = AssetDatabase.GetAllAssetBundleNames();
            foreach (var name in names)
            {
                AssetDatabase.RemoveAssetBundleName(name, true);
            }
        }

        /// <summary>
        /// 打Android AssetBundle
        /// </summary>
        public void BuildAndroidAssetBundle()
        {
            BuildAssetByTarget(BuildTarget.Android);
        }

        /// <summary>
        /// 打Iphone AssetBundle
        /// </summary>
        public void BuildIphoneAssetBundle()
        {
            BuildAssetByTarget(BuildTarget.iOS);
        }

        public void BuildWindowsAssetBundle()
        {
            BuildAssetByTarget(BuildTarget.StandaloneWindows);
        }

        /// <summary>
        /// 清理无用AssetBundle
        /// </summary>
        public void ClearUnusedAssetBundle()
        {
            Debug.Log("开始清理...");
            string clientPath = PathHelper.Ins.GameResPath;
            Dictionary<string, JyFileInfo> clientAbs;
            clientAbs = FileHelper.Ins.ReadFolder(clientPath);

            string abPath = PathHelper.Ins.AssetBundleOutPath;
            Dictionary<string, JyFileInfo> abeds;
            abeds = FileHelper.Ins.ReadFolder(abPath);
            ClearAssetBundle(clientAbs, abeds);
            Debug.Log("清理完成！");
        }

        private void BuildAssetByTarget(BuildTarget target)
        {
            var oldTime = DateTime.Now;
            Debug.Log("开始 Build！" + DateTime.Now);

            // 清理没用的AssetBundle
            ClearUnusedAssetBundle();
            // 清理没用的AssetBundleNames
            ClearUnusedAssetbundleNames();

            GenerateAssetBundleNames();
            string gameResPath = PathHelper.Ins.GameResPath;
            string assetBundlePath = PathHelper.Ins.AssetBundleOutPath;
            string outFilePath = PathHelper.Ins.FileTextPath;
            Debug.Log("Build 中...");
            BuildPipeline.BuildAssetBundles(assetBundlePath, BuildAssetBundleOptions.None, target);

            FileHelper.Ins.GenerateFileText(gameResPath, outFilePath);
            AssetDatabase.Refresh();

            Debug.Log("Build 完成！" + DateTime.Now);
            var newTime = DateTime.Now;
            var dTime = newTime - oldTime;
            Debug.Log("耗时：" + dTime);
        }


        /// <summary>
        /// 分析AssetBundle
        /// </summary>
        private void GenerateAssetBundleNames()
        {
            string resPath = PathHelper.Ins.GameResPath;
            string fileTextPath = PathHelper.Ins.FileTextPath;

            Dictionary<string, JyFileInfo> oldFileDic = new Dictionary<string, JyFileInfo>();
            oldFileDic = FileHelper.Ins.ReadFileText(fileTextPath);

            Dictionary<string, JyFileInfo> needBuildFileDic = new Dictionary<string, JyFileInfo>();

            List<string> fileList = new List<string>();
            List<string> pathList = new List<string>();
            FileHelper.Ins.ReadFile(resPath, ref fileList, ref pathList);

            int fileCnt = fileList.Count;
            for (int i = 0; i < fileCnt; i++)
            {
                string file = fileList[i];
                JyFileInfo jyFile = new JyFileInfo(file);
                // 分析依赖
                AnalysisDependencies(jyFile.AssetPath, ref oldFileDic, ref needBuildFileDic);
            }

            var needBuildList = needBuildFileDic.Values.ToArray();
            var needBuildCnt = needBuildList.Length;
            for (int i = 0; i < needBuildCnt; i++)
            {
                JyFileInfo jyFile = needBuildList[i];

                AssetImporter ai = AssetImporter.GetAtPath(jyFile.AssetPath);
                ai.assetBundleName = jyFile.AssetPath.Substring(jyFile.AssetPath.IndexOf("Assets/") + 7);
                ai.assetBundleVariant = PathHelper.AssetBundleVariant;
            }
        }

        /// <summary>
        /// 分析依赖
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="oldFileDic"></param>
        /// <param name="needBuildFileDic"></param>
        private void AnalysisDependencies(string filePath, ref Dictionary<string, JyFileInfo> oldFileDic,
            ref Dictionary<string, JyFileInfo> needBuildFileDic)
        {
            // 分析依赖
            JyFileInfo jyFile = new JyFileInfo(filePath);
            if ((oldFileDic.ContainsKey(jyFile.Name) && oldFileDic[jyFile.Name].Guid == jyFile.Guid)
                || needBuildFileDic.ContainsKey(jyFile.Name)
                || jyFile.Extension == ".cs")
            {
                // 不用继续打包
                return;
            }
            else
            {
                // 添加到需要打包列表中
                if (!needBuildFileDic.ContainsKey(jyFile.Name))
                {
                    needBuildFileDic.Add(jyFile.Name, jyFile);
                    var depends = AssetDatabase.GetDependencies(filePath);
                    int dependCnt = depends.Length;
                    if (dependCnt > 1)
                    {
                        for (int i = 0; i < dependCnt; i++)
                        {
                            AnalysisDependencies(depends[i], ref oldFileDic, ref needBuildFileDic);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 清理无用AssetBundle
        /// </summary>
        private void ClearAssetBundle(Dictionary<string, JyFileInfo> clientAbs, Dictionary<string, JyFileInfo> abeds)
        {
            string abPath = PathHelper.Ins.AssetBundleOutPath;

            Dictionary<string, List<JyFileInfo>> jyAbs = new Dictionary<string, List<JyFileInfo>>();
            foreach (var ab in abeds)
            {
                var names = ab.Value.Name.Split('.');
                string name;
                if (names.Length >= 2)
                {
                    name = string.Format("{0}.{1}", names[0], names[1]);
                }
                else
                {
                    name = ab.Value.Name;
                }

                if (!jyAbs.ContainsKey(name))
                {
                    List<JyFileInfo> js = new List<JyFileInfo>();
                    js.Add(ab.Value);
                    jyAbs.Add(name, js);
                }
                else
                {
                    jyAbs[name].Add(ab.Value);
                }
            }

            foreach (var ab in jyAbs)
            {
                if (!clientAbs.ContainsKey(ab.Key))
                {
                    // 删除本ab文件
                    foreach (var file in ab.Value)
                    {
                        File.Delete(file.Path);
                    }
                }
            }
        }
    }
}
